﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.IO;
using System.Diagnostics;


namespace SPLogViewer
{
  /// <summary>
  /// Class to observe text file changes. 
  /// </summary>
  class TailReader : IDisposable
  {
    #region public members

    public delegate void NewLinesHandler(List<String> line);
    public event NewLinesHandler NewLines;

    /// <summary>
    /// Interval between checking for updates (ms)
    /// </summary>
    public int UpdateInterval { get; set; }

    /// <summary>
    /// Reader to rad data from
    /// </summary>
    public StreamReader Reader
    {
      get
      {
        return reader;
      }
      set
      {
        reader = value;
        reader.BaseStream.Seek(0, SeekOrigin.Begin);
     }
    }
    private StreamReader reader;

    /// <summary>
    /// Constructor
    /// </summary>
    public TailReader()
    {
      UpdateInterval = 1000;
    }

    /// <summary>
    /// Starts thread to observe stream.
    /// </summary>
    public void Start()
    {

      ThreadStart ts = new ThreadStart(Read);
      listener = new Thread(ts);
      needToStop = false;
      listener.Start();
    }

    /// <summary>
    /// Stops file checking
    /// </summary>
    public void Stop()
    {
      needToStop = true;
    }

    #endregion

    #region protected members

    /// <summary>
    /// Checks if there is new data in the stream and reads lines. If end of file or line limit is reached - NewLines event is rised.
    /// </summary>
    protected void Read()
    {
      if (Reader != null)
      {
        while ((Reader.BaseStream != null) && !needToStop)
        {
          bool firstLine = Reader.BaseStream.Position == 0;
          if (!Reader.EndOfStream)
          {

            string line = "";
            List<string> lines = new List<string>();

            Trace.WriteLine("Read");
            while ((line = Reader.ReadLine()) != null)
            {
              if (!firstLine)
              {
                lines.Add(line);
              }
              else
              {
                firstLine = false;
              }

              if (line.Split(new char[] { '\t' }).Length > 9)
              {
                int x = 0;
              }
              if (lines.Count > READ_LINES)
              {
                NewLines(lines);
                lines = new List<string>();
              }
            }
            if (NewLines != null && lines.Count > 0)
            {
              NewLines(lines);
              lines = new List<string>();
            }
          }
          Thread.Sleep(UpdateInterval);
        }
      }
    }

    #endregion

    #region private members
    /// <summary>
    /// How many lines to read at once
    /// </summary>
    private const int READ_LINES = 500;

    Thread listener = null;

    bool needToStop = false;

    #endregion





    #region IDisposable Members

    public void Dispose()
    {
      Stop();
    }

    #endregion
  }
}
